我是Haskell的新手,并试图了解它是如何工作的?
sequenceA [(+3),(+2),(+1)] 3
我从定义开始
sequenceA :: (Applicative f) => [f a] -> f [a] sequenceA [] = pure [] sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
然后展开递归到此
(:) <$> (+3) <*> $ (:) <$> (+2) <*> $ (:) <$> (+1) <*> pure [] (:) <$> (+3) <*> $ (:) <$> (+2) <*> $ (:) <$> (+1) <*> []
但是在这里我不明白将为哪个应用程序运算符操作符<*>
调用for for for ((->) r)
或for[]
(:) <$> (+1) <*> []
有人可以一步一步地逐步解析sequenceA [(+3),(+2),(+1)] 3
吗?谢谢.
这可以从序列A的类型看出:
sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)
参数的外部类型必须是a Traverable
,其内部类型必须是Applicative
.
现在,当你给sequenceA一个列表(Num a) => [a -> a]
将成为的函数列表时Traversable
,列表中的内容应该是 Applicative
.因此,它使用适用于函数的实例.
因此,当您应用sequenceA时[(+3),(+2),(+1)]
,将构建以下计算:
sequenceA [(+3),(+2),(+1)] = (:) <$> (+3) <*> sequenceA [(+2),(+1)] sequenceA [(+2),(+1)] = (:) <$> (+2) <*> sequenceA [(+1)] sequenceA [(+1)] = (:) <$> (+1) <*> sequenceA [] sequenceA [] = pure []
我们来看看最后一行.pure []
获取一个空列表并将其放入一些应用程序结构中.正如我们刚刚看到的,在这种情况下的应用结构是((->) r)
.因此,sequenceA [] = pure [] = const []
.
现在,第3行可以写成:
sequenceA [(+1)] = (:) <$> (+1) <*> const []
以这种方式组合功能<$>
并<*>
导致并行应用.(+1)
并且const []
都应用于相同的参数,并使用组合结果(:)
因此,sequenceA [(+1)]
返回一个函数,该函数接受一个Num a => a
类型值,应用于(+1)
它,然后将结果预先添加到空列表\x -> (:) ((1+) x) (const [] x)
= \x -> [(+1) x]
.
这个概念可以进一步扩展到sequenceA [(+3), (+2), (+1)]
.它产生一个函数,它接受一个参数,将所有三个函数应用于该参数,并将这三个结果与(:)
在列表中收集它们结合起来:\x -> [(+3) x, (+2) x, (+1) x]
.